﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include "SmartPtr.hpp"
#include <thread>
//using namespace std;


void test1()
{
	using sp::auto_ptr;
	auto_ptr<int> ptr1(new int(1));
	auto_ptr<int> ptr2(new int(2));
	auto_ptr<int> ptr3(ptr1); //管理权平移导致ptr1指针悬空(为空) 可能导致空指针或野指针访问

	cout << *ptr3 << endl;
	cout << *ptr2 << endl;

}

	 
void test2()
{
	struct ts
	{
		ts(int a,int b) 
			:aa(a)
			,bb(b)
		{}
		int aa;
		int bb;
	};

	using sp::unique_ptr;
	unique_ptr<ts> up(new ts(3,4));
	//unique_ptr<ts> copyup(up); //无法拷贝

	cout << up->aa << " " << up->bb << endl;

}
 
void test3()
{
	using sp::shared_ptr;
	shared_ptr<int> ptr1(new int(668));
	shared_ptr<int> ptr2(ptr1);
	shared_ptr<int> ptr3(ptr2);

	cout << *ptr1 << endl;
	cout << *ptr2 << endl;
	cout << *ptr3 << endl;

	shared_ptr<int> ptr4(new int[0]{});

}

void test4()
{
	using sp::shared_ptr;
	using sp::weak_ptr;

	//struct listnode
	//{
	//	shared_ptr<listnode> prev;
	//	shared_ptr<listnode> next;
	//	int val;

	//	~listnode() {
	//		cout << "~listnode" << endl;
	//	}
	//};
	 
	//weak_ptr支持shared_ptr构造，解决其循环引用问题
	struct listnode //使用weak_ptr解决循环引用问题
	{
		weak_ptr<listnode> prev;
		weak_ptr<listnode> next;
		int val;

		~listnode() {
			cout << "~listnode" << endl;
		}
	};
	
	//listnode* n1 = new listnode;
	shared_ptr<listnode> node1(new listnode); //使用shared_ptr可能会发送循环引用问题 此时使用weak_ptr即可
	shared_ptr<listnode> node2(new listnode);
	node1->next = node2;
	node2->prev = node1;

}



struct Date
{
	int _year = 0;
	int _month = 0;
	int _day = 0;

	~Date()
	{}
};

void SharePtrFunc(sp::shared_ptr<Date>& sp, size_t n, mutex& mtx)
{
	using sp::shared_ptr;
	for (size_t i = 0; i < n; ++i)
	{
		// 这里智能指针拷贝会++计数，智能指针析构会--计数，这里是线程安全的。
		sp::shared_ptr<Date> copy(sp);

		mtx.lock();

		sp->_year++;
		sp->_day++;
		sp->_month++;

		mtx.unlock();
	}
}

void test5() //线程安全测试
{
	using sp::shared_ptr;
	const int n = 1000;
	mutex m;
	shared_ptr<Date> sp(new Date);
	
	//两个线程同时对Date进行++

	//线程函数定义引用参数 直接传参是不能构成引用的 必须使用 ref() 处理
	std::thread t1(SharePtrFunc, std::ref(sp), n, std::ref(m));

	std::thread t2(SharePtrFunc, std::ref(sp), n, std::ref(m)); 

	t1.join();
	t2.join();

	cout << sp.use_count() << endl;

	cout << sp->_day << endl;
	cout << sp->_month << endl;
	cout << sp->_year << endl;

}

int main()
{
	test5();

	return 0;
}

